using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace GameOverlayWPF
{
    /// <summary>
    /// 剪贴板操作辅助类，解决 OpenClipboard 失败问题
    /// </summary>
    public static class ClipboardHelper
    {
        private const int MAX_RETRY_COUNT = 10;  // 最大重试次数
        private const int RETRY_DELAY_MS = 50;   // 重试间隔（毫秒）
        
        // Windows API - 用于清除剪贴板锁定状态
        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool CloseClipboard();

        /// <summary>
        /// 安全地设置剪贴板文本（带重试机制）
        /// </summary>
        /// <param name="text">要复制的文本</param>
        /// <returns>是否成功</returns>
        public static bool SetText(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                System.Diagnostics.Debug.WriteLine("剪贴板：文本为空，跳过操作");
                return false;
            }

            // 验证是否在STA线程上
            if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
            {
                System.Diagnostics.Debug.WriteLine("剪贴板：不在STA线程上，无法操作");
                return false;
            }

            Exception lastException = null;

            for (int attempt = 0; attempt < MAX_RETRY_COUNT; attempt++)
            {
                try
                {
                    // 尝试设置剪贴板
                    Clipboard.SetDataObject(text, true);
                    
                    if (attempt > 0)
                    {
                        System.Diagnostics.Debug.WriteLine($"剪贴板：第 {attempt + 1} 次尝试成功");
                    }
                    
                    return true;
                }
                catch (COMException comEx) when (comEx.ErrorCode == unchecked((int)0x800401D0))
                {
                    // CLIPBRD_E_CANT_OPEN - 剪贴板被其他进程占用
                    lastException = comEx;
                    System.Diagnostics.Debug.WriteLine($"剪贴板：第 {attempt + 1} 次尝试失败 (CLIPBRD_E_CANT_OPEN)，{RETRY_DELAY_MS}ms后重试...");
                    
                    if (attempt < MAX_RETRY_COUNT - 1)
                    {
                        // 尝试关闭可能残留的剪贴板句柄
                        try
                        {
                            CloseClipboard();
                        }
                        catch { }
                        
                        // 等待后重试，使用指数退避
                        Thread.Sleep(RETRY_DELAY_MS * (attempt + 1));
                    }
                }
                catch (Exception ex)
                {
                    // 其他异常
                    lastException = ex;
                    System.Diagnostics.Debug.WriteLine($"剪贴板：发生未知错误: {ex.GetType().Name} - {ex.Message}");
                    
                    if (attempt < MAX_RETRY_COUNT - 1)
                    {
                        Thread.Sleep(RETRY_DELAY_MS);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            // 所有重试都失败
            System.Diagnostics.Debug.WriteLine($"剪贴板：所有 {MAX_RETRY_COUNT} 次尝试均失败");
            System.Diagnostics.Debug.WriteLine($"剪贴板：最后错误: {lastException?.Message}");
            return false;
        }

        /// <summary>
        /// 异步设置剪贴板文本（适用于非UI线程调用）
        /// </summary>
        /// <param name="text">要复制的文本</param>
        /// <returns>是否成功</returns>
        public static async Task<bool> SetTextAsync(string text)
        {
            // 确保在UI线程执行
            return await Application.Current.Dispatcher.InvokeAsync(() => SetText(text));
        }

        /// <summary>
        /// 安全地获取剪贴板文本（带重试机制）
        /// </summary>
        /// <returns>剪贴板文本，失败返回null</returns>
        public static string GetText()
        {
            if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
            {
                System.Diagnostics.Debug.WriteLine("剪贴板：不在STA线程上，无法读取");
                return null;
            }

            Exception lastException = null;

            for (int attempt = 0; attempt < MAX_RETRY_COUNT; attempt++)
            {
                try
                {
                    if (Clipboard.ContainsText())
                    {
                        return Clipboard.GetText();
                    }
                    return string.Empty;
                }
                catch (COMException comEx) when (comEx.ErrorCode == unchecked((int)0x800401D0))
                {
                    lastException = comEx;
                    System.Diagnostics.Debug.WriteLine($"剪贴板读取：第 {attempt + 1} 次尝试失败");
                    
                    if (attempt < MAX_RETRY_COUNT - 1)
                    {
                        try { CloseClipboard(); } catch { }
                        Thread.Sleep(RETRY_DELAY_MS * (attempt + 1));
                    }
                }
                catch (Exception ex)
                {
                    lastException = ex;
                    System.Diagnostics.Debug.WriteLine($"剪贴板读取：发生错误: {ex.Message}");
                    break;
                }
            }

            System.Diagnostics.Debug.WriteLine($"剪贴板读取：失败 - {lastException?.Message}");
            return null;
        }

        /// <summary>
        /// 清除剪贴板内容
        /// </summary>
        /// <returns>是否成功</returns>
        public static bool Clear()
        {
            for (int attempt = 0; attempt < MAX_RETRY_COUNT; attempt++)
            {
                try
                {
                    Clipboard.Clear();
                    return true;
                }
                catch (COMException comEx) when (comEx.ErrorCode == unchecked((int)0x800401D0))
                {
                    System.Diagnostics.Debug.WriteLine($"剪贴板清除：第 {attempt + 1} 次尝试失败");
                    
                    if (attempt < MAX_RETRY_COUNT - 1)
                    {
                        try { CloseClipboard(); } catch { }
                        Thread.Sleep(RETRY_DELAY_MS);
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"剪贴板清除失败: {ex.Message}");
                    return false;
                }
            }

            return false;
        }
    }
}
